

class NamedDecorator < DecoratorThing
  attribute :name
  attribute :caption

  def initialize name = nil
    super()
    @name = name.to_s
  end

  def header_label
    s = add_button
    s << human_name #label(:value, caption || name)
    s << label(:name, "property") + InputText.new(
      :name => form_id(:name),
      :id => form_id(:name),
      :value => name
    ).to_s

    s << label(:caption, "caption") + InputText.new(
      :name => form_id(:caption),
      :id => form_id(:caption),
      :value => caption
    ).to_s
    s
  end


  def label id, value = name
    Element.new(
      :label,
      translate(value),
      :id => form_id(id)
    ).to_s
  end

  def form_id attr = nil
    super
  end

  def recieve e
    if name = e.params[form_id :name]
      #puts "set name to #{name}"
      self.name = name
    end
    if caption = e.params[form_id :caption]
      #puts "set caption to #{caption}"
      self.caption = caption
    end

    if child
      child.recieve e
    end
    super
  end

  def has_name?
    name && name.length > 0
  end

  def translate name
    (name || '').split("_").tap { |n|
      (n[0] || '').capitalize!
    }.join(" ")
  end


  def human_name
    self.class.to_s.split("::").last.gsub("Field", '')
  end


  def meta_creator e
    s = ''
    #s << '<div class="thing-meta"><span>'+human_name+'</span> '
    #s << '</div>'
    s << '<div class="thing-default-content">'
    s << creator(e).to_s
    s << '</div>'
    "<div class=\"thing-meta-creator\">" + s + "</div>"
  end

  def thingswecanadd
    [TemplateThing]
  end

end



class NamedField < NamedDecorator
  attribute :value


  def on_plug klass, name, attr
    self.name = name
    #p [name, klass]
    if code = class_body
      begin
        klass.send(:class_eval, code)
      rescue Exception => e
        raise WrappedException.new("Problem: <#{e.message}> while evaluating <#{code.inspect}> on #{klass}", e)
      end
    end
  end

  def creator e
    if child
      child.content = value
    end
    super
  end

  def value
    if root.respond_to? name
      root.send(name)
    else
      @value
    end
  end

  def value= v
    value = validate v
    if root.respond_to? name+'='
      root.send(name+"=", value)
      if child
        child.content = value
      end
      #p "setting value #{v} of #{name} to #{root.title}"
    else
      @value = value
    end
  end

  def validate v
    v
  end


  def recieve e
    if child
      child.content = value
    end
    super
    if child
      self.value = child.content
    end
  end



  class Test < FwTest
    def test_class_body_consists_of_children_class_bodies
      template = ContentTemplate.new
      nf = IntegerField.new(:price)
      template.add nf
      body = template.class_body.first.split("\n")
      eq body[0], 'property :price, Integer'
      eq body[1], 'attr_reader :price'
    end

    def test_get_value_from_parent
      thing = Class.new(ContainerThing) {
        attr_accessor :name
      }.new
      thing.add(nf = StringField.new(:name))
      thing.name = "slim shady"

      eq nf.value, "slim shady"
    end

    def test_parent_value_setter
      thing = Class.new(ContainerThing) {
        attr_accessor :name
      }.new
      thing.add(nf = StringField.new(:name))
      thing.name = "2 unlimited"

      nf.value = "dr. alban"
      eq thing.name, "dr. alban"
    end

    def test_render_displays_value_in_input_text
      thing = Class.new(ContainerThing) {
        attr_accessor :name
      }.new
      thing.add(nf = StringField.new(:name))
      thing.name = "slim shady"

      creator = nf.creator(nil)
      assert creator.match(/value="(.*)"/), creator
      eq creator.match(/value="([^"]*)"/)[1], "slim shady"
    end

    def test_recieve
      thing = Class.new(ContainerThing) {
        attr_accessor :name
      }.new
      nf = StringField.new(:name)
      thing.add nf
      thing.name = "slim shady"

      nf.recieve(Event.new(nil,
          :params => { nf.form_id => "dr. dre"}
        ))
      eq thing.name, "dr. dre", nf.creator(nil)
    end

    def test_recieve_integration
      DataMapper.setup(:test, :adapter => 'in_memory')
      repository(:test) {
        template = ContentTemplate.new
        template.template_class = 'MyNiceBall'
        template.add StringField.new(:color)
        template.save

        ball = template.clone_thing

        ball.color = "red"
        form_fields = ball.creator(Event.new(nil, {:params => {}}))
        assert input = form_fields.match(/<input(.*)value="red"(.*)\/>/)[0]
        assert input_name = input.match(/name="([^"]*)"/)[1]

        ball.recieve(Event.new(nil, {:params => { input_name => 'blue' }}))

        eq ball.color, 'blue'
      }
    end

    def test_new_field_can_display_creator_form
      [StringField, IntegerField].each { |f|
        f.new.creator(
          Event.new(nil, :params  => {})
        )
        assert true
      }
    end
  end
end